#ifndef OPTFRAME_BASICILSPerturbationExato_HPP_
#define OPTFRAME_BASICILSPerturbationExato_HPP_

#include <math.h>
#include <vector>

#include "../../OptFrame/NS.hpp"
#include "../../OptFrame/RandGen.hpp"

template<class R, class M = OPTFRAME_DEFAULT_MEMORY>
class BasicILSPerturbationExato: public BasicILSPerturbation<R, M>
{
private:
	//vector<NS<R, M>*> ns;
	//Evaluator<R, M>& evaluator;
	//int pMax;
	//RandGen& rg;

public:
	BasicILSPerturbationExato(Evaluator<R, M>& e, int _pMax, NS<R, M>& _ns, RandGen& _rg) :
		BasicILSPerturbation<R, M>(e,_pMax, _ns, _rg)
	{
		//ns.push_back(&_ns);
	}

	/*virtual void add_ns(NS<R, M>& _ns)
	{
		ns.push_back(&_ns);
	}*/

	virtual void perturb(Solution<R>& s, Evaluation<M>& e, double timelimit, double target_f)
	{
		int f = 0; // number of failures

		//for (int i = 0; i < ns.size(); i++)
		//		ns.at(i)->print();

		//int numPert = 1;

		//	for (int pert = 0; pert < numPert; pert++)
		//{

		while (f < BasicILSPerturbation<R, M>::pMax)
		{
			int x = BasicILSPerturbation<R, M>::rg.rand(BasicILSPerturbation<R, M>::ns.size());
			for (int i = 0; i < 10; i++)
			{
				Move<R, M>& m = BasicILSPerturbation<R, M>::ns[x]->move(s);

				if (m.canBeApplied(e, s))
				{
					delete &m.apply(e, s);
					delete &m;
					break;
				}
				else
					f++;

				delete &m;

			}

		}
		//	}

		if (f == BasicILSPerturbation<R, M>::pMax)
			cout << "ILS Warning: perturbation had no effect in " << BasicILSPerturbation<R, M>::pMax << " tries!" << endl;

		BasicILSPerturbation<R, M>::evaluator.evaluate(e, s); // updates 'e'
	}
};

#endif /*OPTFRAME_BASICILSPerturbationExato_HPP_*/
